﻿using Outcoder;
using Outcoder.ComponentModel.StatePreservation;
using Outcoder.Concurrency;
using Outcoder.InversionOfControl;
using Outcoder.InversionOfControl.Containers.SimpleContainer;
using Outcoder.Logging;
using Outcoder.Logging.Loggers;
using Outcoder.Messaging;
using Outcoder.NavigationModel;
using Outcoder.Services;
using Outcoder.Services.Implementation;
using Outcoder.UserOptionsModel;

namespace CalciumTemplateApp
{
	/// <summary>
	/// This class initializes various key services. 
	/// Type registrations occur based on the build configuration.
	/// </summary>
	public class Bootstrapper
	{
		readonly StateManager stateManager = new StateManager();
		readonly NavigationMonitor navigationMonitor = new NavigationMonitor();

		public void Run()
		{
			InitializeContainer();
			/* The state manager performs automatic persistence of properties 
			 * when the app is tombstoned or terminated. 
			 * See the PersistencyExampleViewModel. */
			stateManager.Initialize();
			/* The navigation monitor lets the app's viewmodels know when 
			 * a page transition occurs, and allows the viewmodel 
			 * to cancel the navigation. 
			 * The ViewModelBase class contains the current query string. */
			navigationMonitor.Initialize();
		}

		/// <summary>
		/// Initializes the IoC container by registering type associations 
		/// and singleton instances.
		/// </summary>
		void InitializeContainer()
		{
			/* Simple container is the Calcium IoC container that works with Windows Phone. 
			 * It supports both inversion of control and dependency injection. 
			 * It can be accessed globally using the Dependency class. 
			 * The Dependency class leverages the Microsoft ServiceLocator, 
			 * allowing you to change the IoC container implementation. */
			SimpleContainer container = new SimpleContainer();
			container.InitializeContainer();

			/* The following are type associations applicable 
			 * to both build configurations. */

			Dependency.Register<ILog, LocalStorageLog>();

			ISettingsStore localStore = new LocalSettingsStore();
			SettingsService settingsService = new SettingsService(localStore, new RoamingSettingsStore())
				{
					RaiseExceptionsOnConversionErrors = DeploymentConfiguration.DebugBuild
				};
			Dependency.Register<ISettingsService>(settingsService);

			var dialogService = new DialogService
				{
					/* Lambda expressions are used to retrieve the default message service captions, 
					 * which allows the language to be changed at run-time. */
					DefaultMessageCaptionFunc = () => AppResources.DialogService_DefaultMessageCaption,
					DefaultQuestionCaptionFunc = () => AppResources.DialogService_DefaultQuestionCaption,
					DefaultWarningCaptionFunc = () => AppResources.DialogService_DefaultWarningCaption,
					DefaultErrorCaptionFunc = () => AppResources.DialogService_DefaultErrorCaption,
				};
			Dependency.Register<IDialogService>(dialogService);

			Dependency.Register<IProvider<ISynchronizationContext>, UIContextProvider>();
			Dependency.Register<IMessenger, Messenger>(true);
			Dependency.Register<INavigationService, FrameNavigationService>(true);
			Dependency.Register<IUserOptionsService, UserOptionsService>(true);

			AppSettings.InitializeUserOptions();

			/* Build configuration specific associations. */
			if (DeploymentConfiguration.DebugBuild)
			{
				RegisterDebugTypes();
			}
			else
			{
				RegisterReleaseTypes();
			}
		}

		/// <summary>
		/// Registers the debug types. 
		/// Mock types are used for types that cause the app to be deactivated.
		/// </summary>
		void RegisterDebugTypes()
		{
			Dependency.Register<IMarketplaceService>(new MockMarketplaceService { Trial = true });
			//Dependency.Register<IMarketplaceDetailTask>(new MockMarketplaceDetailTask());
		}

		/// <summary>
		/// Registers the release types. 
		/// Since the app will fail marketplace certification if the assembly 
		/// is built using a debug configuration, the release configuration 
		/// guarantees that no mock type registrations will make it into a published app.
		/// </summary>
		void RegisterReleaseTypes()
		{
			Dependency.Register<IMarketplaceService, MarketplaceService>();
			//Dependency.Register<IMarketplaceDetailTask, MarketplaceDetailTaskAdapter>();
		}
	}
}
